﻿namespace Holoville.HOTween.Core
{
    using Holoville.HOTween;
    using Holoville.HOTween.Plugins.Core;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public abstract class ABSTweenComponent : IHOTweenComponent
    {
        internal bool _autoKillOnComplete = true;
        protected int _completedLoops;
        protected bool _destroyed;
        protected float _duration;
        protected float _elapsed;
        internal bool _enabled = true;
        protected float _fullDuration;
        protected float _fullElapsed;
        protected bool _hasStarted;
        internal string _id = string.Empty;
        internal int _intId = -1;
        protected bool _isComplete;
        protected bool _isEmpty = true;
        protected bool _isLoopingBack;
        internal bool _isPaused;
        protected bool _isReversed;
        internal int _loops = 1;
        internal LoopType _loopType = Holoville.HOTween.HOTween.defLoopType;
        protected float _originalDuration;
        protected float _originalNonSpeedBasedDuration;
        internal bool _steadyIgnoreCallbacks;
        internal float _timeScale = Holoville.HOTween.HOTween.defTimeScale;
        internal UpdateType _updateType = Holoville.HOTween.HOTween.defUpdateType;
        internal Sequence contSequence;
        internal bool ignoreCallbacks;
        internal bool manageBehaviours;
        internal Behaviour[] managedBehavioursOff;
        internal Behaviour[] managedBehavioursOn;
        internal bool[] managedBehavioursOriginalState;
        internal GameObject[] managedGameObjectsOff;
        internal GameObject[] managedGameObjectsOn;
        internal bool[] managedGameObjectsOriginalState;
        internal bool manageGameObjects;
        internal TweenDelegate.TweenCallback onComplete;
        internal object[] onCompleteParms;
        internal TweenDelegate.TweenCallbackWParms onCompleteWParms;
        internal TweenDelegate.TweenCallback onPause;
        internal object[] onPauseParms;
        internal TweenDelegate.TweenCallbackWParms onPauseWParms;
        internal TweenDelegate.TweenCallback onPlay;
        internal object[] onPlayParms;
        internal TweenDelegate.TweenCallbackWParms onPlayWParms;
        internal TweenDelegate.TweenCallback onPluginUpdated;
        internal object[] onPluginUpdatedParms;
        internal TweenDelegate.TweenCallbackWParms onPluginUpdatedWParms;
        internal TweenDelegate.TweenCallback onRewinded;
        internal object[] onRewindedParms;
        internal TweenDelegate.TweenCallbackWParms onRewindedWParms;
        internal TweenDelegate.TweenCallback onStart;
        internal object[] onStartParms;
        internal TweenDelegate.TweenCallbackWParms onStartWParms;
        internal TweenDelegate.TweenCallback onStepComplete;
        internal object[] onStepCompleteParms;
        internal TweenDelegate.TweenCallbackWParms onStepCompleteWParms;
        internal TweenDelegate.TweenCallback onUpdate;
        internal object[] onUpdateParms;
        internal TweenDelegate.TweenCallbackWParms onUpdateWParms;
        protected int prevCompletedLoops;
        protected float prevFullElapsed;
        internal bool startupDone;

        protected ABSTweenComponent()
        {
        }

        public void ApplyCallback(CallbackType p_callbackType, TweenDelegate.TweenCallback p_callback)
        {
            this.ApplyCallback(false, p_callbackType, p_callback, null, null);
        }

        public void ApplyCallback(CallbackType p_callbackType, TweenDelegate.TweenCallbackWParms p_callback, params object[] p_callbackParms)
        {
            this.ApplyCallback(true, p_callbackType, null, p_callback, p_callbackParms);
        }

        public void ApplyCallback(CallbackType p_callbackType, GameObject p_sendMessageTarget, string p_methodName, object p_value, SendMessageOptions p_options = 0)
        {
            TweenDelegate.TweenCallbackWParms parms = new TweenDelegate.TweenCallbackWParms(Holoville.HOTween.HOTween.DoSendMessage);
            object[] objArray = new object[] { p_sendMessageTarget, p_methodName, p_value, p_options };
            this.ApplyCallback(true, p_callbackType, null, parms, objArray);
        }

        protected virtual void ApplyCallback(bool p_wParms, CallbackType p_callbackType, TweenDelegate.TweenCallback p_callback, TweenDelegate.TweenCallbackWParms p_callbackWParms, params object[] p_callbackParms)
        {
            switch (p_callbackType)
            {
                case CallbackType.OnStart:
                    this.onStart = p_callback;
                    this.onStartWParms = p_callbackWParms;
                    this.onStartParms = p_callbackParms;
                    break;

                case CallbackType.OnUpdate:
                    this.onUpdate = p_callback;
                    this.onUpdateWParms = p_callbackWParms;
                    this.onUpdateParms = p_callbackParms;
                    break;

                case CallbackType.OnStepComplete:
                    this.onStepComplete = p_callback;
                    this.onStepCompleteWParms = p_callbackWParms;
                    this.onStepCompleteParms = p_callbackParms;
                    break;

                case CallbackType.OnComplete:
                    this.onComplete = p_callback;
                    this.onCompleteWParms = p_callbackWParms;
                    this.onCompleteParms = p_callbackParms;
                    break;

                case CallbackType.OnPause:
                    this.onPause = p_callback;
                    this.onPauseWParms = p_callbackWParms;
                    this.onPauseParms = p_callbackParms;
                    break;

                case CallbackType.OnPlay:
                    this.onPlay = p_callback;
                    this.onPlayWParms = p_callbackWParms;
                    this.onPlayParms = p_callbackParms;
                    break;

                case CallbackType.OnRewinded:
                    this.onRewinded = p_callback;
                    this.onRewindedWParms = p_callbackWParms;
                    this.onRewindedParms = p_callbackParms;
                    break;

                case CallbackType.OnPluginOverwritten:
                    TweenWarning.Log("ApplyCallback > OnPluginOverwritten type is available only with Tweeners and not with Sequences");
                    break;
            }
        }

        public void Complete()
        {
            this.Complete(true);
        }

        internal abstract void Complete(bool p_doAutoKill);
        internal abstract void FillPluginsList(List<ABSTweenPlugin> p_plugs);
        internal abstract List<IHOTweenComponent> GetTweensById(string p_id);
        internal abstract List<IHOTweenComponent> GetTweensByIntId(int p_intId);
        public abstract List<object> GetTweenTargets();
        public bool GoTo(float p_time)
        {
            return this.GoTo(p_time, false, false, false);
        }

        public bool GoTo(float p_time, bool p_forceUpdate)
        {
            return this.GoTo(p_time, false, p_forceUpdate, false);
        }

        internal bool GoTo(float p_time, bool p_forceUpdate, bool p_ignoreCallbacks)
        {
            return this.GoTo(p_time, false, p_forceUpdate, p_ignoreCallbacks);
        }

        protected abstract bool GoTo(float p_time, bool p_play, bool p_forceUpdate, bool p_ignoreCallbacks);
        public bool GoToAndPlay(float p_time)
        {
            return this.GoTo(p_time, true, false, false);
        }

        public bool GoToAndPlay(float p_time, bool p_forceUpdate)
        {
            return this.GoTo(p_time, true, p_forceUpdate, false);
        }

        internal bool GoToAndPlay(float p_time, bool p_forceUpdate, bool p_ignoreCallbacks)
        {
            return this.GoTo(p_time, true, p_forceUpdate, p_ignoreCallbacks);
        }

        public abstract bool IsLinkedTo(object p_target);
        public abstract bool IsTweening(int p_id);
        public abstract bool IsTweening(object p_target);
        public abstract bool IsTweening(string p_id);
        public void Kill()
        {
            this.Kill(true);
        }

        internal virtual void Kill(bool p_autoRemoveFromHOTween)
        {
            if (!this._destroyed)
            {
                this._destroyed = this._isEmpty = true;
                if (p_autoRemoveFromHOTween)
                {
                    Holoville.HOTween.HOTween.Kill(this);
                }
            }
        }

        protected void ManageObjects(bool isPlay)
        {
            if (this.manageBehaviours)
            {
                int length = 0;
                if (this.managedBehavioursOn != null)
                {
                    length = this.managedBehavioursOn.Length;
                    for (int i = 0; i < this.managedBehavioursOn.Length; i++)
                    {
                        Behaviour behaviour = this.managedBehavioursOn[i];
                        if (behaviour != null)
                        {
                            if (isPlay)
                            {
                                this.managedBehavioursOriginalState[i] = behaviour.enabled;
                                behaviour.enabled = true;
                            }
                            else
                            {
                                behaviour.enabled = this.managedBehavioursOriginalState[i];
                            }
                        }
                    }
                }
                if (this.managedBehavioursOff != null)
                {
                    for (int j = 0; j < this.managedBehavioursOff.Length; j++)
                    {
                        Behaviour behaviour2 = this.managedBehavioursOff[j];
                        if (behaviour2 != null)
                        {
                            if (isPlay)
                            {
                                this.managedBehavioursOriginalState[length + j] = behaviour2.enabled;
                                behaviour2.enabled = false;
                            }
                            else
                            {
                                behaviour2.enabled = this.managedBehavioursOriginalState[j + length];
                            }
                        }
                    }
                }
            }
            if (this.manageGameObjects)
            {
                int num4 = 0;
                if (this.managedGameObjectsOn != null)
                {
                    num4 = this.managedGameObjectsOn.Length;
                    for (int k = 0; k < this.managedGameObjectsOn.Length; k++)
                    {
                        GameObject obj2 = this.managedGameObjectsOn[k];
                        if (obj2 != null)
                        {
                            if (isPlay)
                            {
                                this.managedGameObjectsOriginalState[k] = obj2.active;
                                obj2.active = true;
                            }
                            else
                            {
                                obj2.active = this.managedGameObjectsOriginalState[k];
                            }
                        }
                    }
                }
                if (this.managedGameObjectsOff != null)
                {
                    for (int m = 0; m < this.managedGameObjectsOff.Length; m++)
                    {
                        GameObject obj3 = this.managedGameObjectsOff[m];
                        if (obj3 != null)
                        {
                            if (isPlay)
                            {
                                this.managedGameObjectsOriginalState[num4 + m] = obj3.active;
                                obj3.active = false;
                            }
                            else
                            {
                                obj3.active = this.managedGameObjectsOriginalState[m + num4];
                            }
                        }
                    }
                }
            }
        }

        protected void OnComplete()
        {
            this._isComplete = true;
            this.OnStepComplete();
            if ((!this.steadyIgnoreCallbacks && !this.ignoreCallbacks) && ((this.onComplete != null) || (this.onCompleteWParms != null)))
            {
                if (Holoville.HOTween.HOTween.isUpdateLoop)
                {
                    Holoville.HOTween.HOTween.onCompletes.Add(this);
                }
                else
                {
                    this.OnCompleteDispatch();
                }
            }
        }

        internal void OnCompleteDispatch()
        {
            if (this.onComplete != null)
            {
                this.onComplete();
            }
            else if (this.onCompleteWParms != null)
            {
                this.onCompleteWParms(new TweenEvent(this, this.onCompleteParms));
            }
        }

        protected void OnPause()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                this.ManageObjects(false);
                if (this.onPause != null)
                {
                    this.onPause();
                }
                else if (this.onPauseWParms != null)
                {
                    this.onPauseWParms(new TweenEvent(this, this.onPauseParms));
                }
            }
        }

        protected virtual void OnPlay()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                this.ManageObjects(true);
                if (this.onPlay != null)
                {
                    this.onPlay();
                }
                else if (this.onPlayWParms != null)
                {
                    this.onPlayWParms(new TweenEvent(this, this.onPlayParms));
                }
            }
        }

        protected void OnPluginUpdated(ABSTweenPlugin p_plugin)
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                if (this.onPluginUpdated != null)
                {
                    this.onPluginUpdated();
                }
                else if (this.onPluginUpdatedWParms != null)
                {
                    this.onPluginUpdatedWParms(new TweenEvent(this, this.onPluginUpdatedParms, p_plugin));
                }
            }
        }

        protected void OnRewinded()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                if (this.onRewinded != null)
                {
                    this.onRewinded();
                }
                else if (this.onRewindedWParms != null)
                {
                    this.onRewindedWParms(new TweenEvent(this, this.onRewindedParms));
                }
            }
        }

        protected virtual void OnStart()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                this._hasStarted = true;
                if (this.onStart != null)
                {
                    this.onStart();
                }
                else if (this.onStartWParms != null)
                {
                    this.onStartWParms(new TweenEvent(this, this.onStartParms));
                }
                this.OnPlay();
            }
        }

        protected void OnStepComplete()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                if (this.onStepComplete != null)
                {
                    this.onStepComplete();
                }
                else if (this.onStepCompleteWParms != null)
                {
                    this.onStepCompleteWParms(new TweenEvent(this, this.onStepCompleteParms));
                }
            }
        }

        protected void OnUpdate()
        {
            if (!this.steadyIgnoreCallbacks && !this.ignoreCallbacks)
            {
                if (this.onUpdate != null)
                {
                    this.onUpdate();
                }
                else if (this.onUpdateWParms != null)
                {
                    this.onUpdateWParms(new TweenEvent(this, this.onUpdateParms));
                }
            }
        }

        public void Pause()
        {
            if (this._enabled && !this._isPaused)
            {
                this._isPaused = true;
                this.OnPause();
            }
        }

        public void Play()
        {
            if (this._enabled)
            {
                this.PlayIfPaused();
            }
        }

        public void PlayBackwards()
        {
            if (this._enabled)
            {
                this._isReversed = true;
                this.PlayIfPaused();
            }
        }

        public void PlayForward()
        {
            if (this._enabled)
            {
                this._isReversed = false;
                this.PlayIfPaused();
            }
        }

        private void PlayIfPaused()
        {
            if (this._isPaused && ((!this._isReversed && !this._isComplete) || (this._isReversed && (this._fullElapsed > 0f))))
            {
                this._isPaused = false;
                this.OnPlay();
            }
        }

        protected virtual void Reset()
        {
            this._id = string.Empty;
            this._intId = -1;
            this._autoKillOnComplete = true;
            this._enabled = true;
            this._timeScale = Holoville.HOTween.HOTween.defTimeScale;
            this._loops = 1;
            this._loopType = Holoville.HOTween.HOTween.defLoopType;
            this._updateType = Holoville.HOTween.HOTween.defUpdateType;
            this._isPaused = false;
            this._completedLoops = 0;
            this._duration = this._originalDuration = this._originalNonSpeedBasedDuration = this._fullDuration = 0f;
            this._elapsed = this._fullElapsed = 0f;
            this._isEmpty = true;
            this._isReversed = this._isLoopingBack = this._hasStarted = this._isComplete = false;
            this.startupDone = false;
            this.onStart = null;
            this.onStartWParms = null;
            this.onStartParms = null;
            this.onUpdate = null;
            this.onUpdateWParms = null;
            this.onUpdateParms = null;
            this.onPluginUpdated = null;
            this.onPluginUpdatedWParms = null;
            this.onPluginUpdatedParms = null;
            this.onStepComplete = null;
            this.onStepCompleteWParms = null;
            this.onStepCompleteParms = null;
            this.onComplete = null;
            this.onCompleteWParms = null;
            this.onCompleteParms = null;
            this.onPause = null;
            this.onPauseWParms = null;
            this.onPauseParms = null;
            this.onPlay = null;
            this.onPlayWParms = null;
            this.onPlayParms = null;
            this.onRewinded = null;
            this.onRewindedWParms = null;
            this.onRewindedParms = null;
            this.manageBehaviours = false;
            this.managedBehavioursOff = null;
            this.managedBehavioursOn = null;
            this.managedBehavioursOriginalState = null;
            this.manageGameObjects = false;
            this.managedGameObjectsOff = null;
            this.managedGameObjectsOn = null;
            this.managedGameObjectsOriginalState = null;
        }

        public abstract void Restart();
        public void Reverse(bool p_forcePlay = false)
        {
            if (this._enabled)
            {
                this._isReversed = !this._isReversed;
                if (p_forcePlay)
                {
                    this.Play();
                }
            }
        }

        public abstract void Rewind();
        protected void SetElapsed()
        {
            if ((this._duration == 0f) || ((this._loops >= 0) && (this._completedLoops >= this._loops)))
            {
                this._elapsed = this._duration;
            }
            else if (this._fullElapsed < this._duration)
            {
                this._elapsed = this._fullElapsed;
            }
            else
            {
                this._elapsed = this._fullElapsed % this._duration;
            }
        }

        protected void SetFullDuration()
        {
            this._fullDuration = (this._loops >= 0) ? (this._duration * this._loops) : float.PositiveInfinity;
        }

        internal abstract void SetIncremental(int p_diffIncr);
        protected void SetLoops()
        {
            if (this._duration == 0f)
            {
                this._completedLoops = 1;
            }
            else
            {
                float num = this._fullElapsed / this._duration;
                int num2 = (int) Math.Ceiling((double) num);
                if ((num2 - num) < 1E-07f)
                {
                    this._completedLoops = num2;
                }
                else
                {
                    this._completedLoops = num2 - 1;
                }
            }
            this._isLoopingBack = ((this._loopType != LoopType.Restart) && (this._loopType != LoopType.Incremental)) && (((this._loops > 0) && (((this._completedLoops < this._loops) && ((this._completedLoops % 2) != 0)) || ((this._completedLoops >= this._loops) && ((this._completedLoops % 2) == 0)))) || ((this._loops < 0) && ((this._completedLoops % 2) != 0)));
        }

        protected virtual void Startup()
        {
            this.startupDone = true;
        }

        internal bool Update(float p_elapsed)
        {
            return this.Update(p_elapsed, false, false, false);
        }

        internal bool Update(float p_elapsed, bool p_forceUpdate)
        {
            return this.Update(p_elapsed, p_forceUpdate, false, false);
        }

        internal bool Update(float p_elapsed, bool p_forceUpdate, bool p_isStartupIteration)
        {
            return this.Update(p_elapsed, p_forceUpdate, p_isStartupIteration, false);
        }

        internal abstract bool Update(float p_elapsed, bool p_forceUpdate, bool p_isStartupIteration, bool p_ignoreCallbacks);
        [DebuggerHidden]
        public IEnumerator WaitForCompletion()
        {
            return new <WaitForCompletion>c__Iterator11 { <>f__this = this };
        }

        [DebuggerHidden]
        public IEnumerator WaitForRewind()
        {
            return new <WaitForRewind>c__Iterator12 { <>f__this = this };
        }

        public bool autoKillOnComplete
        {
            get
            {
                return this._autoKillOnComplete;
            }
            set
            {
                this._autoKillOnComplete = value;
            }
        }

        public int completedLoops
        {
            get
            {
                return this._completedLoops;
            }
        }

        public bool destroyed
        {
            get
            {
                return this._destroyed;
            }
        }

        public float duration
        {
            get
            {
                return this._duration;
            }
        }

        public float elapsed
        {
            get
            {
                return this._elapsed;
            }
        }

        public bool enabled
        {
            get
            {
                return this._enabled;
            }
            set
            {
                this._enabled = value;
            }
        }

        public float fullDuration
        {
            get
            {
                return this._fullDuration;
            }
        }

        public float fullElapsed
        {
            get
            {
                return this._fullElapsed;
            }
        }

        public bool hasStarted
        {
            get
            {
                return this._hasStarted;
            }
        }

        public string id
        {
            get
            {
                return this._id;
            }
            set
            {
                this._id = value;
            }
        }

        public int intId
        {
            get
            {
                return this._intId;
            }
            set
            {
                this._intId = value;
            }
        }

        public bool isComplete
        {
            get
            {
                return this._isComplete;
            }
        }

        public bool isEmpty
        {
            get
            {
                return this._isEmpty;
            }
        }

        public bool isLoopingBack
        {
            get
            {
                return this._isLoopingBack;
            }
        }

        public bool isPaused
        {
            get
            {
                return this._isPaused;
            }
        }

        public bool isReversed
        {
            get
            {
                return this._isReversed;
            }
        }

        public bool isSequenced
        {
            get
            {
                return (this.contSequence != null);
            }
        }

        public int loops
        {
            get
            {
                return this._loops;
            }
            set
            {
                this._loops = value;
                this.SetFullDuration();
            }
        }

        public LoopType loopType
        {
            get
            {
                return this._loopType;
            }
            set
            {
                this._loopType = value;
            }
        }

        public float position
        {
            get
            {
                return ((this._loops >= 1) ? this._fullElapsed : this._elapsed);
            }
            set
            {
                this.GoTo(value, !this._isPaused);
            }
        }

        internal virtual bool steadyIgnoreCallbacks
        {
            get
            {
                return this._steadyIgnoreCallbacks;
            }
            set
            {
                this._steadyIgnoreCallbacks = value;
            }
        }

        public float timeScale
        {
            get
            {
                return this._timeScale;
            }
            set
            {
                this._timeScale = value;
            }
        }

        public UpdateType updateType
        {
            get
            {
                return this._updateType;
            }
        }

        [CompilerGenerated]
        private sealed class <WaitForCompletion>c__Iterator11 : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal ABSTweenComponent <>f__this;

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                    case 1:
                        if (!this.<>f__this._isComplete)
                        {
                            this.$current = 0;
                            this.$PC = 1;
                            return true;
                        }
                        break;

                    default:
                        break;
                        this.$PC = -1;
                        break;
                }
                return false;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }

        [CompilerGenerated]
        private sealed class <WaitForRewind>c__Iterator12 : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal ABSTweenComponent <>f__this;

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                    case 1:
                        if (this.<>f__this._fullElapsed > 0f)
                        {
                            this.$current = 0;
                            this.$PC = 1;
                            return true;
                        }
                        break;

                    default:
                        break;
                        this.$PC = -1;
                        break;
                }
                return false;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }
    }
}

